using Godot;
using System;

namespace CurrentGame.GUI;


public partial class SingleLineText : Label
{
	[Signal]
	public delegate void SingleLineFinishedEventHandler();

	[Export]
	public string ShowText
	{
		get => _targetText;
		set
		{
			PrepareSingleLine(value);
		}
	}
	private string _targetText, _currentText;

	[Export]
	public float StayDuration { get; set; } = 1.0f;
	[Export]
	public float Interval { get; set; } = 0.01f;

	[ExportGroup("Typing settings")]
	[Export]
	public bool EnableTyping { get; set; } = false;
	[Export]
	public float TypingSpeed { get; set; } = 20.0f;

	[ExportGroup("Fade settings")]
	[Export]
	public bool EnableFade { get; set; } = false;
	[Export]
	public float FadeFactor { get; set; } = 0.3f;


	// animation states
	private bool _stateTyping = false, _stateShow = false, _stateFade = false;
	private int _textProgress = 0;
	private float _floatProgress = 0.0f, _showTime = 0.0f, _currentAlpha = 1.0f;

	// time tick
	private double _time = 0.0;

	private void PrepareSingleLine(string text)
	{
        Modulate = new Color(1.0f, 1.0f, 1.0f, 1.0f);
        Visible = true;
		Text = "";
		_currentText = "";
		_targetText = text;
		_textProgress = 0;
		_floatProgress = 0.0f;
		_showTime = 0.0f;
		_currentAlpha = 1.0f;
		_stateTyping = true;
	}

	private void FixedUpdate(double delta)
	{
		if (_stateTyping)
		{
			if (EnableTyping)
			{
				_floatProgress += (float)delta * TypingSpeed;
				if (_floatProgress >= _textProgress)
				{
					_textProgress += 1;
					if (_textProgress <= _targetText.Length)
					{
						Text = _targetText.Substring(0, _textProgress);
					}
					else
					{
                        _stateTyping = false;
                        _stateShow = true;
                    }
				}
			}
			else
			{
				_stateTyping = false;
				_stateShow = true;
				Text = _targetText;
			}
		}
		else if (_stateShow)
		{
			_showTime += (float)delta;
			if (_showTime > StayDuration)
			{
				_stateShow = false;
				_stateFade = true;
				_currentAlpha = 1.0f;
			}
		}
		else if (_stateFade)
		{
			if (EnableFade)
			{
				_currentAlpha = Mathf.Lerp(_currentAlpha, 0.0f, FadeFactor);
				if (_currentAlpha < 0.001f)
				{
					_currentAlpha = 0.0f;
                    _stateFade = false;
                    Visible = false;
                    EmitSignal(SignalName.SingleLineFinished);
                }
				else
				{
					Modulate = new Color(1.0f, 1.0f, 1.0f, _currentAlpha);
				}
			}
			else
			{
				_stateFade = false;
				Visible = false;
				EmitSignal(SignalName.SingleLineFinished);
			}
		}
	}

	public override void _Process(double delta)
	{
		_time += delta;
        if (_time > Interval)
        {
			FixedUpdate(_time);
			_time = 0.0f;
        }
    }
}
